Skip to content

[박예진-15주차 알고리즘 스터디] #91

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

uiop5809
Copy link
Member

@uiop5809 uiop5809 commented Apr 28, 2025

🚀 싸피 15반 알고리즘 스터디 15주차 [박예진]

📌 문제 풀이 개요

  • 이번 PR에서는 다음 5문제의 풀이를 포함합니다.
  • 각 문제에 대한 풀이 과정과 접근 방식을 설명합니다.

✅ 문제 해결 여부

  • 문제 1 : 온풍기 안녕!
  • 문제 2 : 후위 표기식
  • 문제 3 : 행복 유치원
  • 문제 4 : 나머지 합
  • 문제 5 : 제곱수의 합

💡 풀이 방법

문제 1: 온풍기 안녕!

문제 난이도

문제 유형

접근 방식 및 풀이


문제 2: 후위 표기식

문제 난이도
골드2

문제 유형
스택, 자료구조

접근 방식 및 풀이
스택을 사용해서 문제를 풀었다.
알파벳일 경우에는 답 string에 추가를 바로 했고,
사칙연산과 괄호일 경우에는 swtich 조건식을 사용해서 풀었다.

만약에 (일 경우에는 스택에 바로 푸시해주었고,
우선순위가 높은 *, /이 나올 경우에는 s.top()이 *, /일때까지 res+=s.top(), s.pop()을 반복후 넣어줬다.
우선순위가 낮은 +, -이 나올 경우에는 s.top()이 (이 아닐 때까지 res+=s.top(), s.pop()을 반복후 넣어줬다.
만약에 )일 경우에는 s.top이 (이 아닐 때까지 res+=s.top(), s.pop()을 반복후 괄호를 없애줬다. 문을 닫는 느낌

모든 string을 다 돌았을 때도 스택이 차있다면 res에 추가해준다.

for (int i = 0; i < str.size(); i++) {
		if ('A' <= str[i] && str[i] <= 'Z') {
			res += str[i];
		}
		else {
			switch (str[i]) {
			case '(':
				s.push(str[i]);
				break;
			case '*':
			case '/':
				while (!s.empty() && (s.top() == '*' || s.top() == '/')) {
					res += s.top();
					s.pop();
				}
				s.push(str[i]);
				break;
			case '+':
			case '-':
				while (!s.empty() && s.top() != '(') {
					res += s.top();
					s.pop();
				}
				s.push(str[i]);
				break;
			case ')':
				while (!s.empty() && s.top() != '(') {
					res += s.top();
					s.pop();
				}
				s.pop();
				break;
			}
		}
	}

문제 3: 행복 유치원

문제 난이도
골드5

문제 유형
그리디, 정렬

접근 방식 및 풀이
조마다 티셔츠를 맞추는 비용이 조에서 가장 키가 큰 원생과 가장 키가 작은 원생의 키 차이만큼 든다고 한다.
각 K개의 조에 대해 티셔츠 만드는 비용의 합을 최소로 하는 문제이므로 그리디를 생각할 수 있었다.

각 배열 앞뒤의 차이를 벡터에 넣고, 오름차순을 한 뒤
N - K개만큼 더해주면 되는 문제이다.

만약에 N = 5, K = 3
1 3 5 6 10이면
앞뒤의 차이가 2, 2, 1, 4이고 정렬을 하면 1, 2, 2, 4일 것이다.
(1,3), (5,6) (10) 이렇게 나누어지므로 N - K = 2개까지만 세면 된다. 10은 차이가 없으니 2 + 1 = 3이다.


문제 4: 나머지 합

문제 난이도
골드3

문제 유형
수학

접근 방식 및 풀이
수학 문제라서 어려웠다.
연속된 부분 구간의 합이 M으로 나누어 떨어지는 구간의 개수를 구하는 문제이다.
N이 10^6이기 때문에 2중 반복문을 하면 터진다.
따라서 O(nlong)이나 O(n)을 사용해야한다.
따라서 누적합을 사용하면서, 나머지를 저장해놓는 방법을 사용했다.

(preSum[j] - preSum[i]) % M == 0
이라고 하면 preSum[j] % M == preSum[i] % M 이므로
나머지가 0이 아니라 아무 값이나 같기만 하면 된다.

N = 5, M = 3이고 1 2 3 1 2일 때,
구간합을 구하면 0 1 3 6 7 9 이다.
나머지를 구하면 0 1 0 0 1 0 이다.

나머지 같은 것의 각각 개수를 구하면 0이 4개, 1이 2개이다.
각각의 구간의 개수를 구하는 것이기 때문에 nC2를 해야한다.
4C2 + 1C2 = 6 + 1 = 7이다.


문제 5: 제곱수의 합

문제 난이도
실버2

문제 유형
dp

접근 방식 및 풀이
처음에는 현재 값의 가장 큰 제곱수를 빼준 dp값을 구해 + 1을 하면 되는 문제인 줄 알았다.
그러나, dp[12] 같은 경우엔 가장 큰 제곱수가 3^2= 9임에도 불구하고, 2^2 + 2^2 + 2^2 = 12로
9 + 1 + 1 + 1 보다 4 + 4 + 4로 푸는 게 더 적은 제곱수가 필요했다.

따라서, 2중 반복문 사용하여 현재보다 작은 모든 제곱수를 뺐을 경우 최솟값을 업데이트 해줘야한다.

	for (int i = 1; i <= N; i++) {
		dp[i] = i;
		for (int j = 1; j * j <= i; j++) {
			dp[i] = min(dp[i], dp[i - j * j] + 1);
		}
	}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant